home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2003 August / MW 8 2003 CD1.iso / Inside Macworld / Product News / gimp-1.2.4.sit / gimp-1.2.4 / plug-ins / common / illusion.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-19  |  17.2 KB  |  661 lines

  1. /*
  2.  * illusion.c  -- This is a plug-in for the GIMP 1.0
  3.  *  
  4.  * Copyright (C) 1997  Hirotsuna Mizuno
  5.  *                     s1041150@u-aizu.ac.jp
  6.  *
  7.  * Preview and new mode added May 2000 by tim copperfield
  8.  *                timecop@japan.co.jp
  9.  *                http://www.ne.jp/asahi/linux/timecop
  10.  *
  11.  * This program is free software; you can redistribute it and/or modify it
  12.  * under the terms of the GNU General Public License as published by the Free
  13.  * Software Foundation; either version 2 of the License, or (at your option)
  14.  * any later version.
  15.  *
  16.  * This program is distributed in the hope that it will be useful, but WITHOUT
  17.  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  18.  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  19.  * more details.
  20.  *
  21.  * You should have received a copy of the GNU General Public License along with
  22.  * this program; if not, write to the Free Software Foundation, Inc.,
  23.  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  24.  *
  25.  */
  26.  
  27. #include "config.h"
  28.  
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32.  
  33. #include <gtk/gtk.h>
  34.  
  35. #include <libgimp/gimp.h>
  36. #include <libgimp/gimpui.h>
  37.  
  38. #include "libgimp/stdplugins-intl.h"
  39.  
  40.  
  41. #define PLUG_IN_NAME    "plug_in_illusion"
  42. #define PLUG_IN_VERSION "v0.8 (May 14 2000)"
  43.  
  44. #define PREVIEW_SIZE    128 
  45.  
  46. /******************************************************************************/
  47.  
  48. static void      query  (void);
  49. static void      run    (gchar   *name,
  50.              gint     nparam,
  51.              GimpParam  *param,
  52.              gint    *nreturn_vals,
  53.              GimpParam **return_vals);
  54.  
  55. static void      filter                  (GimpDrawable *drawable);
  56. static void      filter_preview          (void);
  57. static void      fill_preview_with_thumb (GtkWidget *preview_widget, 
  58.                       gint32     drawable_ID);
  59. static gboolean  dialog                  (GimpDrawable *drawable);
  60.  
  61. /******************************************************************************/
  62.  
  63. typedef struct
  64. {
  65.   gint32 division;
  66.   gint   type1;
  67.   gint   type2;
  68. } IllValues;
  69.  
  70. /******************************************************************************/
  71.  
  72. GimpPlugInInfo PLUG_IN_INFO =
  73. {
  74.   NULL,  /* init_proc  */
  75.   NULL,  /* quit_proc  */
  76.   query, /* query_proc */
  77.   run    /* run_proc   */
  78. };
  79.  
  80. static IllValues parameters =
  81. {
  82.   8, /* division */
  83.   1, /* type 1 */
  84.   0  /* type 2 */
  85. };
  86.  
  87.  
  88. static GtkWidget *preview;
  89. static guchar    *preview_cache;
  90. static gint       preview_cache_rowstride;
  91. static gint       preview_cache_bpp;
  92.  
  93. /******************************************************************************/
  94.  
  95. MAIN ()
  96.  
  97. /******************************************************************************/
  98.  
  99. static void
  100. query (void)
  101. {
  102.   static GimpParamDef args[] =
  103.   {
  104.     { GIMP_PDB_INT32,    "run_mode",  "interactive / non-interactive" },
  105.     { GIMP_PDB_IMAGE,    "image",     "input image" },
  106.     { GIMP_PDB_DRAWABLE, "drawable",  "input drawable" },
  107.     { GIMP_PDB_INT32,    "division",  "the number of divisions" },
  108.     { GIMP_PDB_INT32,    "type",      "illusion type (0=type1, 1=type2)" }
  109.   };
  110.   static gint nargs = sizeof (args) / sizeof (args[0]);
  111.  
  112.   gimp_install_procedure (PLUG_IN_NAME,
  113.               "produce illusion",
  114.               "produce illusion",
  115.               "Hirotsuna Mizuno <s1041150@u-aizu.ac.jp>",
  116.               "Hirotsuna Mizuno",
  117.               PLUG_IN_VERSION,
  118.               N_("<Image>/Filters/Map/Illusion..."),
  119.               "RGB*, GRAY*",
  120.               GIMP_PLUGIN,
  121.               nargs, 0,
  122.               args, NULL);
  123. }
  124.  
  125. /******************************************************************************/
  126.  
  127. static void
  128. run (gchar   *name,
  129.      gint     nparams,
  130.      GimpParam  *params,
  131.      gint    *nreturn_vals,
  132.      GimpParam **return_vals)
  133. {
  134.   GimpDrawable     *drawable;
  135.   GimpRunModeType   run_mode;
  136.   static GimpParam  returnv[1];
  137.   GimpPDBStatusType    status = GIMP_PDB_SUCCESS;
  138.  
  139.   run_mode = params[0].data.d_int32;
  140.   drawable = gimp_drawable_get (params[2].data.d_drawable);
  141.   *nreturn_vals = 1;
  142.   *return_vals  = returnv;
  143.  
  144.   /* get the drawable info */
  145.  
  146.   /* switch the run mode */
  147.   switch (run_mode)
  148.     {
  149.     case GIMP_RUN_INTERACTIVE:
  150.       INIT_I18N_UI();
  151.       gimp_get_data (PLUG_IN_NAME, ¶meters);
  152.       if (! dialog(drawable))
  153.     return;
  154.       gimp_set_data (PLUG_IN_NAME, ¶meters, sizeof (IllValues));
  155.       g_free(preview_cache);
  156.       break;
  157.  
  158.     case GIMP_RUN_NONINTERACTIVE:
  159.       if (nparams != 5)
  160.     {
  161.       status = GIMP_PDB_CALLING_ERROR;
  162.     }
  163.       else
  164.     {
  165.       parameters.division = params[3].data.d_int32;
  166.           if (params[4].data.d_int32 == 0)
  167.             {
  168.               parameters.type1 = 1;
  169.               parameters.type2 = 0;
  170.             }
  171.           else
  172.             {
  173.               parameters.type1 = 0;
  174.               parameters.type2 = 1;
  175.             }
  176.     }
  177.       break;
  178.  
  179.     case GIMP_RUN_WITH_LAST_VALS:
  180.       gimp_get_data (PLUG_IN_NAME, ¶meters);
  181.       break;
  182.     }
  183.  
  184.   if (status == GIMP_PDB_SUCCESS)
  185.     {
  186.       if (gimp_drawable_is_rgb (drawable->id) || 
  187.       gimp_drawable_is_gray (drawable->id))
  188.     {
  189.       gimp_tile_cache_ntiles (2 * (drawable->width / gimp_tile_width() + 1));
  190.         gimp_progress_init (_("Illusion..."));
  191.       filter (drawable);
  192.       if (run_mode != GIMP_RUN_NONINTERACTIVE)
  193.         gimp_displays_flush ();
  194.     }
  195.       else
  196.     {
  197.       status = GIMP_PDB_EXECUTION_ERROR;
  198.     }
  199.     }
  200.  
  201.   returnv[0].type          = GIMP_PDB_STATUS;
  202.   returnv[0].data.d_status = status;
  203.  
  204.   gimp_drawable_detach (drawable);
  205. }
  206.  
  207. /******************************************************************************/
  208.  
  209. static void
  210. filter (GimpDrawable *drawable)
  211. {
  212.   GimpPixelRgn srcPR, destPR;
  213.   guchar  **pixels;
  214.   guchar  **destpixels;
  215.   
  216.   gint    image_width;
  217.   gint    image_height;
  218.   gint    image_bpp;
  219.   gint    image_has_alpha;
  220.   gint    x1;
  221.   gint    y1;
  222.   gint    x2;
  223.   gint    y2;
  224.   gint    select_width;
  225.   gint    select_height;
  226.   gdouble center_x;
  227.   gdouble center_y;
  228.  
  229.   gint      x, y, b;
  230.   gint      xx = 0;
  231.   gint      yy = 0;
  232.   gdouble   scale, radius, cx, cy, angle, offset;
  233.  
  234.   image_width     = gimp_drawable_width (drawable->id);
  235.   image_height    = gimp_drawable_height (drawable->id);
  236.   image_bpp       = gimp_drawable_bpp (drawable->id);
  237.   image_has_alpha = gimp_drawable_has_alpha (drawable->id);
  238.   gimp_drawable_mask_bounds (drawable->id,&x1, &y1, &x2, &y2);
  239.   select_width    = x2 - x1;
  240.   select_height   = y2 - y1;
  241.   center_x        = x1 + (gdouble)select_width / 2;
  242.   center_y        = y1 + (gdouble)select_height / 2;
  243.   
  244.   gimp_pixel_rgn_init (&srcPR, drawable,
  245.                0, 0, image_width, image_height, FALSE, FALSE);
  246.   gimp_pixel_rgn_init (&destPR, drawable,
  247.                0, 0, image_width, image_height, TRUE, TRUE);
  248.  
  249.   pixels     = g_new (guchar *, image_height);
  250.   destpixels = g_new (guchar *, image_height);
  251.  
  252.   for (y = 0; y < image_height; y++)
  253.     {
  254.       pixels[y]     = g_new (guchar, image_width * image_bpp);
  255.       destpixels[y] = g_new (guchar, image_width * image_bpp);
  256.       gimp_pixel_rgn_get_row (&srcPR, pixels[y], 0, y, image_width);
  257.     }
  258.  
  259.   scale = sqrt (select_width * select_width + select_height * select_height) / 2;
  260.   offset = (gint) (scale / 2);
  261.  
  262.   for (y = y1; y < y2; y++)
  263.     {
  264.       cy = ((gdouble)y - center_y) / scale; 
  265.       for (x = x1; x < x2; x++)
  266.     {
  267.       cx = ((gdouble)x - center_x) / scale;
  268.       angle = floor (atan2 (cy, cx) * parameters.division / G_PI_2)
  269.         * G_PI_2 / parameters.division + (G_PI / parameters.division);
  270.       radius = sqrt ((gdouble) (cx * cx + cy * cy));
  271.  
  272.       if (parameters.type1) 
  273.         {
  274.           xx = x - offset * cos (angle);
  275.           yy = y - offset * sin (angle);
  276.         }
  277.  
  278.       if (parameters.type2) 
  279.         {
  280.           xx = x - offset * sin (angle);
  281.           yy = y - offset * cos (angle);
  282.         }
  283.  
  284.       if (xx < 0) 
  285.         xx = 0;
  286.       else if (image_width <= xx) 
  287.         xx = image_width - 1;
  288.  
  289.       if (yy < 0) 
  290.         yy = 0;
  291.       else if (image_height <= yy) 
  292.         yy = image_height - 1;
  293.  
  294.       for (b = 0; b < image_bpp; b++)
  295.         destpixels[y][x*image_bpp+b] =
  296.           (1-radius) * pixels[y][x * image_bpp + b] 
  297.           + radius * pixels[yy][xx * image_bpp + b];
  298.     }
  299.       gimp_pixel_rgn_set_row (&destPR, destpixels[y], 0, y, image_width);
  300.       gimp_progress_update ((double) (y - y1) / (double) select_height);
  301.     }
  302.  
  303.   gimp_drawable_flush (drawable);
  304.   gimp_drawable_merge_shadow (drawable->id, TRUE);
  305.   gimp_drawable_update (drawable->id,
  306.             x1, y1, select_width, select_height);
  307.  
  308.   for (y = y1; y < y2; y++) g_free (pixels[y-y1]);
  309.   g_free (pixels);
  310.   for (y = y1; y < y2; y++) g_free (destpixels[y-y1]);
  311.   g_free (destpixels);
  312. }
  313.  
  314. static void
  315. preview_do_row(gint    row,
  316.            gint    width,
  317.            guchar *even,
  318.            guchar *odd,
  319.            guchar *src)
  320. {
  321.   gint    x;
  322.   
  323.   guchar *p0 = even;
  324.   guchar *p1 = odd;
  325.   
  326.   gdouble    r, g, b, a;
  327.   gdouble    c0, c1;
  328.   
  329.   for (x = 0; x < width; x++) 
  330.     {
  331.       if (preview_cache_bpp == 4)
  332.     {
  333.       r = ((gdouble)src[x*4+0]) / 255.0;
  334.       g = ((gdouble)src[x*4+1]) / 255.0;
  335.       b = ((gdouble)src[x*4+2]) / 255.0;
  336.       a = ((gdouble)src[x*4+3]) / 255.0;
  337.     }
  338.       else if (preview_cache_bpp == 3)
  339.     {
  340.       r = ((gdouble)src[x*3+0]) / 255.0;
  341.       g = ((gdouble)src[x*3+1]) / 255.0;
  342.       b = ((gdouble)src[x*3+2]) / 255.0;
  343.       a = 1.0;
  344.     }
  345.       else
  346.     {
  347.       r = ((gdouble)src[x*preview_cache_bpp+0]) / 255.0;
  348.       g = b = r;
  349.       if (preview_cache_bpp == 2)
  350.             a = ((gdouble)src[x*preview_cache_bpp+1]) / 255.0;
  351.       else
  352.         a = 1.0;
  353.     }
  354.       
  355.       if ((x / GIMP_CHECK_SIZE) & 1) 
  356.     {
  357.       c0 = GIMP_CHECK_LIGHT;
  358.       c1 = GIMP_CHECK_DARK;
  359.     } 
  360.       else 
  361.     {
  362.       c0 = GIMP_CHECK_DARK;
  363.       c1 = GIMP_CHECK_LIGHT;
  364.     }
  365.       
  366.       *p0++ = (c0 + (r - c0) * a) * 255.0;
  367.       *p0++ = (c0 + (g - c0) * a) * 255.0;
  368.       *p0++ = (c0 + (b - c0) * a) * 255.0;
  369.       
  370.       *p1++ = (c1 + (r - c1) * a) * 255.0;
  371.       *p1++ = (c1 + (g - c1) * a) * 255.0;
  372.       *p1++ = (c1 + (b - c1) * a) * 255.0;
  373.       
  374.     } /* for */
  375.   
  376.   if ((row / GIMP_CHECK_SIZE) & 1)
  377.     {
  378.       gtk_preview_draw_row (GTK_PREVIEW (preview), (guchar *)odd,  0, row, width); 
  379.     }
  380.   else
  381.     {
  382.       gtk_preview_draw_row (GTK_PREVIEW (preview), (guchar *)even, 0, row, width); 
  383.     }
  384. }
  385.  
  386. static void
  387. filter_preview (void)
  388. {
  389.   guchar  **pixels;
  390.   guchar  **destpixels;
  391.   guchar  *even, *odd;
  392.   
  393.   gint      image_width;
  394.   gint      image_height;
  395.   gint      image_bpp;
  396.   gdouble   center_x;
  397.   gdouble   center_y;
  398.  
  399.   gint      x, y, b;
  400.   gint      xx = 0;
  401.   gint      yy = 0;
  402.   gdouble   scale, radius, cx, cy, angle, offset;
  403.  
  404.   image_width  = GTK_PREVIEW (preview)->buffer_width;
  405.   image_height = GTK_PREVIEW (preview)->buffer_height;
  406.   image_bpp    = preview_cache_bpp;
  407.   center_x     = (gdouble)image_width  / 2;
  408.   center_y     = (gdouble)image_height / 2;
  409.     
  410.   pixels     = g_new (guchar *, image_height);
  411.   destpixels = g_new (guchar *, image_height);
  412.  
  413.   even = g_malloc (image_width * 3);
  414.   odd  = g_malloc (image_width * 3);
  415.  
  416.   for (y = 0; y < image_height; y++)
  417.     {
  418.       pixels[y]     = g_new (guchar, preview_cache_rowstride);
  419.       destpixels[y] = g_new (guchar, preview_cache_rowstride);
  420.       memcpy (pixels[y], 
  421.           preview_cache + preview_cache_rowstride * y, 
  422.           preview_cache_rowstride);
  423.     }
  424.  
  425.   scale  = sqrt (image_width * image_width + image_height * image_height) / 2;
  426.   offset = (gint) (scale / 2);
  427.  
  428.   for (y = 0; y < image_height; y++)
  429.     {
  430.       cy = ((gdouble)y - center_y) / scale; 
  431.       for (x = 0; x < image_width; x++)
  432.     {
  433.       cx = ((gdouble)x - center_x) / scale;
  434.       angle = floor (atan2 (cy, cx) * parameters.division / G_PI_2)
  435.         * G_PI_2 / parameters.division + (G_PI / parameters.division);
  436.       radius = sqrt ((gdouble) (cx * cx + cy * cy));
  437.  
  438.       if (parameters.type1) 
  439.         {
  440.           xx = x - offset * cos (angle);
  441.           yy = y - offset * sin (angle);
  442.         }
  443.  
  444.       if (parameters.type2) 
  445.         {
  446.           xx = x - offset * sin (angle);
  447.           yy = y - offset * cos (angle);
  448.         }
  449.  
  450.       if (xx < 0) 
  451.         xx = 0;
  452.       else if (image_width <= xx) 
  453.         xx = image_width - 1;
  454.  
  455.       if (yy < 0) 
  456.         yy = 0;
  457.       else if (image_height <= yy) 
  458.         yy = image_height - 1;
  459.  
  460.       for (b = 0; b < image_bpp; b++)
  461.         destpixels[y][x*image_bpp+b] =
  462.           (1-radius) * pixels[y][x * image_bpp + b] 
  463.           + radius * pixels[yy][xx * image_bpp + b];
  464.     }
  465.  
  466.       preview_do_row(y,
  467.              image_width,
  468.              even,
  469.              odd,
  470.              destpixels[y]);
  471.     }
  472.  
  473.   for (y = 0; y < image_height; y++) 
  474.     g_free (pixels[y]);
  475.   g_free (pixels);
  476.  
  477.   for (y = 0; y < image_height; y++) 
  478.     g_free (destpixels[y]);
  479.   g_free (destpixels);
  480.  
  481.   g_free (even);
  482.   g_free (odd);
  483.  
  484.   gtk_widget_queue_draw (preview);
  485. }
  486.  
  487. static GtkWidget *
  488. preview_widget (GimpDrawable *drawable)
  489. {
  490.   preview = gtk_preview_new (GTK_PREVIEW_COLOR);
  491.   fill_preview_with_thumb (preview, drawable->id);
  492.  
  493.   return preview;
  494. }
  495.  
  496. static void
  497. fill_preview_with_thumb (GtkWidget *widget, 
  498.              gint32     drawable_ID)
  499. {
  500.   guchar  *drawable_data;
  501.   gint     bpp;
  502.   gint     y;
  503.   gint     width  = PREVIEW_SIZE;
  504.   gint     height = PREVIEW_SIZE;
  505.   guchar  *src;
  506.   guchar  *even, *odd;
  507.  
  508.   bpp = 0; /* Only returned */
  509.   
  510.   drawable_data = 
  511.     gimp_drawable_get_thumbnail_data (drawable_ID, &width, &height, &bpp);
  512.  
  513.   if (width < 1 || height < 1)
  514.     return;
  515.  
  516.   preview_cache = drawable_data;
  517.   preview_cache_rowstride = width * bpp;
  518.   preview_cache_bpp = bpp;
  519.  
  520.   gtk_preview_size (GTK_PREVIEW (widget), width, height);
  521.  
  522.   even = g_malloc (width * 3);
  523.   odd  = g_malloc (width * 3);
  524.   src = drawable_data;
  525.  
  526.   for (y = 0; y < height; y++)
  527.     {
  528.       preview_do_row(y,width,even,odd,preview_cache + (y*width*bpp));
  529.     }
  530.  
  531.   g_free (even);
  532.   g_free (odd);
  533. }
  534.  
  535. /******************************************************************************/
  536.  
  537. static gboolean dialog_status = FALSE;
  538.  
  539. static void
  540. dialog_ok_handler (GtkWidget *widget,
  541.            gpointer   data)
  542. {
  543.   dialog_status = TRUE;
  544.  
  545.   gtk_widget_destroy (GTK_WIDGET (data));
  546. }
  547.  
  548. /******************************************************************************/
  549.  
  550. static gboolean
  551. dialog (GimpDrawable *mangle)
  552. {
  553.   GtkWidget *dlg;  
  554.   GtkWidget *main_vbox;
  555.   GtkWidget *abox;
  556.   GtkWidget *frame;
  557.   GtkWidget *table;
  558.   GtkWidget *spinbutton;
  559.   GtkObject *adj;
  560.   GtkWidget *radio;
  561.   GSList    *group = NULL;
  562.  
  563.   gimp_ui_init ("illusion", TRUE);
  564.  
  565.   dlg = gimp_dialog_new (_("Illusion"), "illusion",
  566.              gimp_standard_help_func, "filters/illusion.html",
  567.              GTK_WIN_POS_MOUSE,
  568.              FALSE, TRUE, FALSE,
  569.              
  570.              _("OK"), dialog_ok_handler,
  571.              NULL, NULL, NULL, TRUE, FALSE,
  572.              _("Cancel"), gtk_widget_destroy,
  573.              NULL, 1, NULL, FALSE, TRUE,
  574.              
  575.              NULL);
  576.  
  577.   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
  578.               GTK_SIGNAL_FUNC (gtk_main_quit),
  579.               NULL);
  580.  
  581.   /* Initialize Tooltips */
  582.   gimp_help_init ();
  583.   
  584.   main_vbox = gtk_vbox_new (FALSE, 3);
  585.   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 0);
  586.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), main_vbox, TRUE, TRUE, 0);
  587.   gtk_widget_show (main_vbox);
  588.  
  589.   frame = gtk_frame_new (_("Preview"));
  590.   gtk_container_set_border_width (GTK_CONTAINER (frame), 6);
  591.   gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
  592.   gtk_widget_show (frame);
  593.   abox = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
  594.   gtk_container_set_border_width (GTK_CONTAINER (abox), 4);
  595.   gtk_container_add (GTK_CONTAINER (frame), abox);
  596.   gtk_widget_show (abox);
  597.   frame = gtk_frame_new (NULL);
  598.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
  599.   gtk_container_add (GTK_CONTAINER (abox), frame);
  600.   gtk_widget_show (frame);
  601.   preview = preview_widget (mangle);
  602.   gtk_container_add (GTK_CONTAINER (frame), preview);
  603.   filter_preview();
  604.   gtk_widget_show (preview);
  605.   
  606.   frame = gtk_frame_new (_("Parameter Settings"));
  607.   gtk_container_set_border_width (GTK_CONTAINER (frame), 6);
  608.   gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0 );
  609.   gtk_widget_show (frame);
  610.  
  611.   table = gtk_table_new (3, 2, FALSE);
  612.   gtk_container_set_border_width (GTK_CONTAINER (table), 4);
  613.   gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  614.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  615.   gtk_container_add (GTK_CONTAINER (frame), table);
  616.   gtk_widget_show (table);
  617.  
  618.   spinbutton = gimp_spin_button_new (&adj, parameters.division,
  619.                      -32, 64, 1, 10, 0, 1, 0);
  620.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
  621.                  _("Division:"), 1.0, 0.5,
  622.                  spinbutton, 1, TRUE);
  623.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  624.               GTK_SIGNAL_FUNC (gimp_int_adjustment_update),
  625.               ¶meters.division);
  626.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  627.               GTK_SIGNAL_FUNC (filter_preview),
  628.               NULL);
  629.  
  630.   radio = gtk_radio_button_new_with_label (group, _("Mode 1"));
  631.   group = gtk_radio_button_group (GTK_RADIO_BUTTON (radio));
  632.   gtk_signal_connect (GTK_OBJECT (radio), "toggled",
  633.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  634.               ¶meters.type1);
  635.   gtk_signal_connect (GTK_OBJECT (radio), "toggled",
  636.               GTK_SIGNAL_FUNC (filter_preview),
  637.               NULL);
  638.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio), parameters.type1);
  639.   gtk_table_attach (GTK_TABLE (table), radio, 0, 2, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
  640.   gtk_widget_show (radio);
  641.  
  642.   radio = gtk_radio_button_new_with_label (group, _("Mode 2"));
  643.   group = gtk_radio_button_group (GTK_RADIO_BUTTON (radio));
  644.   gtk_signal_connect (GTK_OBJECT (radio), "toggled",
  645.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  646.               ¶meters.type2);
  647.   gtk_signal_connect (GTK_OBJECT (radio), "toggled",
  648.               GTK_SIGNAL_FUNC (filter_preview),
  649.               NULL);
  650.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio), parameters.type2);
  651.   gtk_table_attach (GTK_TABLE (table), radio, 0, 2, 2, 3, GTK_FILL, GTK_FILL, 0, 0);
  652.   gtk_widget_show (radio);
  653.  
  654.   gtk_widget_show (dlg);
  655.  
  656.   gtk_main ();
  657.   gdk_flush ();
  658.  
  659.   return dialog_status;
  660. }
  661.